/*
 * atk_ms53l0_iic.h
 * ATK-MS53L0模块软件模拟I2C通信接口头文件
 * 提供软件模拟I2C的底层操作函数声明和硬件引脚定义
 */

#ifndef __ATK_MS53L0_IIC_H
#define __ATK_MS53L0_IIC_H

#include "./SYSTEM/sys/sys.h"  /* 包含系统头文件 */

/* 引脚定义 ***************************************************************************/

/**
 * @brief   I2C时钟线SCL引脚定义
 * @note    连接到VL53L0X传感器的SCL引脚
 */
#define ATK_MS53L0_IIC_SCL_GPIO_PORT            GPIOB                        /* SCL引脚端口 */
#define ATK_MS53L0_IIC_SCL_GPIO_PIN             GPIO_PIN_10                  /* SCL引脚编号 */
#define ATK_MS53L0_IIC_SCL_GPIO_CLK_ENABLE()    do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)  /* SCL引脚时钟使能 */

/**
 * @brief   I2C数据线SDA引脚定义
 * @note    连接到VL53L0X传感器的SDA引脚
 */
#define ATK_MS53L0_IIC_SDA_GPIO_PORT            GPIOB                        /* SDA引脚端口 */
#define ATK_MS53L0_IIC_SDA_GPIO_PIN             GPIO_PIN_11                  /* SDA引脚编号 */
#define ATK_MS53L0_IIC_SDA_GPIO_CLK_ENABLE()    do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)  /* SDA引脚时钟使能 */

/* IO操作宏 **************************************************************************/
/**
 * @brief   设置SCL引脚电平
 * @param   x: 引脚电平状态，0为低电平，非0为高电平
 */
#define ATK_MS53L0_IIC_SCL(x)                   do{ x ?                                                                                             \
                                                    HAL_GPIO_WritePin(ATK_MS53L0_IIC_SCL_GPIO_PORT, ATK_MS53L0_IIC_SCL_GPIO_PIN, GPIO_PIN_SET) :    \
                                                    HAL_GPIO_WritePin(ATK_MS53L0_IIC_SCL_GPIO_PORT, ATK_MS53L0_IIC_SCL_GPIO_PIN, GPIO_PIN_RESET);   \
                                                }while(0)

/**
 * @brief   设置SDA引脚电平
 * @param   x: 引脚电平状态，0为低电平，非0为高电平
 */
#define ATK_MS53L0_IIC_SDA(x)                   do{ x ?                                                                                             \
                                                    HAL_GPIO_WritePin(ATK_MS53L0_IIC_SDA_GPIO_PORT, ATK_MS53L0_IIC_SDA_GPIO_PIN, GPIO_PIN_SET) :    \
                                                    HAL_GPIO_WritePin(ATK_MS53L0_IIC_SDA_GPIO_PORT, ATK_MS53L0_IIC_SDA_GPIO_PIN, GPIO_PIN_RESET);   \
                                                }while(0)

/**
 * @brief   读取SDA引脚电平
 * @return  引脚当前电平状态，0为低电平，1为高电平
 */
#define ATK_MS53L0_IIC_READ_SDA()               HAL_GPIO_ReadPin(ATK_MS53L0_IIC_SDA_GPIO_PORT, ATK_MS53L0_IIC_SDA_GPIO_PIN)

/* 函数声明 ***************************************************************************/

/**
 * @brief   发送IIC起始信号
 * @note    起始信号：在SCL为高电平期间，SDA从高电平向低电平切换
 * @param   无
 * @retval  无
 */
void atk_ms53l0_iic_start(void);                /* 发送IIC起始信号 */

/**
 * @brief   发送IIC停止信号
 * @note    停止信号：在SCL为高电平期间，SDA从低电平向高电平切换
 * @param   无
 * @retval  无
 */
void atk_ms53l0_iic_stop(void);                 /* 发送IIC停止信号 */

/**
 * @brief   等待IIC应答信号
 * @note    包含超时检测机制，防止程序陷入死循环
 * @param   无
 * @retval  0: 应答信号接收成功
 *          1: 应答信号接收失败
 */
uint8_t atk_ms53l0_iic_wait_ack(void);          /* 等待IIC应答信号 */

/**
 * @brief   发送ACK应答信号
 * @note    ACK信号：在第9个时钟脉冲期间，SDA保持低电平
 * @param   无
 * @retval  无
 */
void atk_ms53l0_iic_ack(void);                  /* 发送ACK应答信号 */

/**
 * @brief   发送非ACK应答信号
 * @note    NACK信号：在第9个时钟脉冲期间，SDA保持高电平
 * @param   无
 * @retval  无
 */
void atk_ms53l0_iic_nack(void);                 /* 发送NACK应答信号 */

/**
 * @brief   IIC发送一个字节
 * @note    数据发送格式：高位在前，低位在后
 * @param   dat: 要发送的数据
 * @retval  无
 */
void atk_ms53l0_iic_send_byte(uint8_t dat);     /* IIC发送一个字节 */

/**
 * @brief   IIC读取一个字节
 * @note    数据接收格式：高位在前，低位在后
 * @param   ack: ack=1时发送ACK；ack=0时发送NACK
 * @retval  接收到的数据
 */
uint8_t atk_ms53l0_iic_read_byte(uint8_t ack);  /* IIC读取一个字节 */

/**
 * @brief   初始化IIC接口
 * @note    配置SCL引脚为推挽输出模式，SDA引脚为开漏输出模式
 * @param   无
 * @retval  无
 */
void atk_ms53l0_iic_init(void);                 /* 初始化IIC接口 */

#endif
